﻿using SW2A311_Lib;
using System;
using System.Net;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;

namespace Client
{
    /// <summary>
    /// Klassen som håndterer vores WPF applikation.
    /// </summary>
    /// <remarks>
    /// I klassen er alt hvad der har med vores GUi at gøre, inkl. alt exception-handling og eventhandling i forhold til vores GUI.
    /// </remarks>
    public partial class MainWindow : Window
    {
        #region Instansvariabler
        /// <summary>
        /// BAAAK !?
        /// </summary>
        internal EventDrivenShare EDS;
        /// <summary>
        /// Netværkstråden.
        /// </summary>
        private Thread NetThread;
        /// <summary>
        /// Netværksstream'et.
        /// </summary>
        private Network StreamHandler;
        private User currUser;

        /// <summary>
        /// ProjectDatabasen "instantieres" vha. <c>ProjectCollection</c> klassen.
        /// </summary>
        private ProjectCollection ProjectDB = ProjectCollection.Instance;

        /// <summary>
        /// Delegate som er nødvendig for vores <c>GuiInputHandler</c> til at bruge <c>BeginInvoke</c>.
        /// </summary>
        public static HandleChatMessage DelegateChatMessage;
        /// <summary>
        /// Delegate som er nødvendig for vores <c>GuiInputHandler</c> til at bruge <c>BeginInvoke</c>.
        /// </summary>
        public static HandleProjectData DelegateProjectData;
        /// <summary>
        /// Delegate som er nødvendig for vores <c>GuiInputHandler</c> til at bruge <c>BeginInvoke</c>.
        /// </summary>
        public static ConnectStatus DelegateConnectStatus;
        #endregion

        #region Constructors
        /// <summary>
        /// Constructor til til vores GUI .
        /// </summary>
        /// <remarks>
        /// Kalder den autogenererede <c>InitializeComponent</c> for at starte vores XAML-kode. 
        /// </remarks>
        public MainWindow()
        {
            InitializeComponent();
        }
        #endregion

        #region Eventhandlers
        /// <summary>
        /// En delegate til at håndtere vores chatbeskeder.
        /// </summary>
        /// <param name="Message">Er en <c>EventDrivenShare.ChatMessageArgs</c>.</param>
        public delegate void HandleChatMessage(object Message);
        /// <summary>
        /// Sørger for at placere chatbeskeden i vores chatbox.
        /// </summary>
        /// <param name="Message">Er en <c>EventDrivenShare.ChatMessageArgs</c>.</param>
        private void AppendChatMessageToTextbox(object Message)
        {
            EventDrivenShare.ChatMessageArgs ChatMessage = (EventDrivenShare.ChatMessageArgs)Message;
            ChatTextBox.AppendText(ChatMessage.ChatMessage);
            ChatTextBox.AppendText("\n");
        }
        /// <summary>
        /// En delegate til at håndtere vores projekter.
        /// </summary>
        /// <param name="Message">Er en <c>EventDrivenShare.ProjectArgs</c>.</param>
        public delegate void HandleProjectData(object Message);
        /// <summary>
        /// Sørger for at et nyt projekt fra serveren bliver tilføjet til instansen af <c>ProjectCollection</c>.
        /// </summary>
        /// <param name="Message">Er en <c>EventDrivenShare.ProjectArgs</c>.</param>
        private void AddProjectDataToList(object Message)
        {
            EventDrivenShare.ProjectArgs projectData = (EventDrivenShare.ProjectArgs)Message;

            CreateProject(projectData.Project);
        }
        #endregion

        #region Chat
        /// <summary>
        /// Event der køres når <c>ChatMessageTextBox</c> får fokus fra brugeren.
        /// </summary>
        /// <param name="sender">Indeholder information om hvor eventet kommer fra.</param>
        /// <param name="e">Indeholder information omkring det specifikke event.</param>
        private void ChatMessageTextBox_GotFocus(object sender, RoutedEventArgs e)
        {
            InitializeTextBoxOnGotFocus(ChatMessageTextBox, "Enter a chatmessage", SendChatMessageButton);
        }
        /// <summary>
        /// Event der køres når <c>ChatMessageTextBox</c> mister fokus fra brugeren.
        /// </summary>
        /// <param name="sender">Indeholder information om hvor eventet kommer fra.</param>
        /// <param name="e">Indeholder information omkring det specifikke event.</param>
        private void ChatMessageTextBox_LostFocus(object sender, RoutedEventArgs e)
        {
            InitializeTextBoxOnLostFocus(ChatMessageTextBox, "Enter a chatmessage");
        }
        /// <summary>
        /// Event der køres når der klikkes på <c>SendChatMessageButton</c>.
        /// </summary>
        /// <remarks>
        /// Sørger for at sende den string som er i <c>ChatMessageTextBox</c> til serveren. 
        /// Gør kun noget hvis <c>ChatMessageTextBox</c> indeholder andet end whitespace og teksten er forskellige fra standard-teksten.
        /// </remarks>
        /// <param name="sender">Indeholder information om hvor eventet kommer fra.</param>
        /// <param name="e">Indeholder information omkring det specifikke event.</param>
        private void SendChatMessageButton_Click(object sender, RoutedEventArgs e)
        {
            string defaultString = "Enter a chatmessage";
            if (!ChatMessageTextBox.Text.Equals(defaultString) && !ChatMessageTextBox.Text.Equals(""))
            {
                ChatTextBox.Text += String.Format("Me: {0}\n", ChatMessageTextBox.Text);
                ChatMessageEncapsulation chatMsg = new ChatMessageEncapsulation(currUser.Username);
                chatMsg.ChatMessageContent = ChatMessageTextBox.Text;
                EDS.Encapsulation = new EncapsulationClass(chatMsg);
            }
            ChatMessageTextBox.Clear();
        }
        /// <summary>
        /// Event der køres når teksten i <c>ChatTextBox</c> ændres.
        /// </summary>
        /// <remarks>
        /// Sørger for altid at scrolle til bunden af tekstboksen når der kommer ny tekst derind.
        /// </remarks>
        /// <param name="sender">Indeholder information om hvor eventet kommer fra.</param>
        /// <param name="e">Indeholder information omkring det specifikke event.</param>
        private void ChatTextBox_TextChanged(object sender, TextChangedEventArgs e)
        {
            ChatTextBox.ScrollToEnd();
        }
        #endregion

        #region Global actions
        /// <summary>
        /// Laver en opgave til et valgt projekt.
        /// </summary>
        /// <remarks>
        /// Opretter en instans af <c>Task</c> og sørger for at fange exceptions for invalid input så brugeren informeres herom. Opdaterer derudover opgavelisten.
        /// </remarks>
        /// <param name="pd">Instansen af <c>ProjectData</c> som opgaves tilføjes til.</param>
        /// <param name="taskName">Er navnet på opgaven som oprettes.</param>
        /// <param name="taskDescription">Beskrivelsen på opgaven.</param>
        /// <param name="taskStart">Starttidspunktet for opgaven.</param>
        /// <param name="taskEnd">Sluttidspunktet for opgaven</param>
        private void CreateTask(ProjectData pd, string taskName, string taskDescription, DateTime taskStart, DateTime taskEnd)
        {
            try
            {
                Task task = new Task(taskEnd, taskStart, taskName, taskDescription);
                ProjectDB.AddTaskToProject(pd, task);
                EDS.Encapsulation = new EncapsulationClass(ProjectDB.FindProjectByName(pd.ProjectName));
            }
            catch (NullReferenceException)
            {
                MessageBox.Show("Please select a project first!", "Create task", MessageBoxButton.OK, MessageBoxImage.Stop);
            }
            catch (ArgumentOutOfRangeException)
            {
                MessageBox.Show("Please enter dates within project period!", "Create task", MessageBoxButton.OK, MessageBoxImage.Stop);
            }
            finally
            {
                RefreshTaskList();
            }
        }
        /// <summary>
        /// Laver et nyt projekt fra GUI'en.
        /// </summary>
        /// <remarks>
        /// Opretter en instans af <c>ProjectData</c> og sørger for at fange exceptions for invalid input så brugeren informeres herom. 
        /// Opdaterer derudover <c>ProjectComboBox</c> så alle projekter er deri.
        /// </remarks>
        /// <param name="projectName">Navnet på projektet</param>
        /// <param name="projectStart">Starttidspunktet for projektet</param>
        /// <param name="projectEnd">Sluttidspunktet for projektet</param>l
        private void CreateProject(string projectName, DateTime projectStart, DateTime projectEnd)
        {
            try
            {
                ProjectData tempProject = new ProjectData(projectName, projectStart, projectEnd, currUser.Username);
                ProjectDB.Add(tempProject);
                RefreshProjectComboBox();
                ProjectComboBox.SelectedIndex = ProjectDB.IndexOf(tempProject);
                EDS.Encapsulation = new EncapsulationClass(tempProject);
            }
            catch (ArgumentOutOfRangeException)
            {
                MessageBox.Show("Please validate the input!", "Create Project", MessageBoxButton.OK, MessageBoxImage.Stop);
            }
            finally
            {
                RefreshProjectComboBox();
            }
        }
        /// <summary>
        /// Lavet et nyt projekt fra serveren.
        /// </summary>
        /// <remarks>
        /// Bliver kørt når serveren sender et nyt projekt til klienten.
        /// Gemmes herefter i instansen af <c>ProjectCollection</c>.
        /// </remarks>
        /// <param name="pd"><c>ProjectData</c>-instanen som serveren sender</param>
        private void CreateProject(ProjectData pd)
        {
            //Blir kaldt når server sender nyt projekt
            try
            {
                ProjectDB.Add(pd);
            }
            catch (ArgumentException)
            {
                MessageBox.Show("Please validate the input!", "Create Project", MessageBoxButton.OK, MessageBoxImage.Stop);
            }
            finally
            {
                RefreshProjectComboBox();
            }
        }
        /// <summary>
        /// Opretter en ny bruger
        /// </summary>
        /// <remarks>
        /// Opretter en instans af <c>User</c>-klassen og sørger for at fange exceptions for invalid input så brugeren informeres herom.
        /// Sender ligeledes den nye bruger til serveren så den opdaterer.
        /// </remarks>
        /// <param name="userName">Brugernavnet for den nye bruger</param>
        /// <param name="passWord">Kodeordet for den nye bruger</param>
        private void CreateUser(string userName, string passWord)
        {
            try
            {
                User userToCreate = new User(NotifCreateUserUsernameTextbox.Text, NotifCreateUserPasswordPasswordBox.Password);
                EncapsulationClass enc = new EncapsulationClass(userToCreate);
                enc.SetAsCreateUser();
                EDS.Encapsulation = enc;
            }
            catch (ArgumentNullException)
            {
                MessageBox.Show("Neither username or password can be null or whitespace!", "Create User", MessageBoxButton.OK, MessageBoxImage.Stop);
            }
            catch (ArgumentOutOfRangeException)
            {
                MessageBox.Show("Username must be at least 3 characters long and password must be at least 6 characters long!", "Create User", MessageBoxButton.OK, MessageBoxImage.Stop);
            }

        }
        #endregion

        #region Left Grid
        /// <summary>
        /// Event der køres når der klikkes på <c>CreateTaskButton</c>.
        /// </summary>
        /// <remarks>
        /// Sørger for kun at vise vinduet til at oprette opgaver, når der er valgt et projekt og hvis man er "admin" på projektet.
        /// </remarks>
        /// <param name="sender">Indeholder information om hvor eventet kommer fra.</param>
        /// <param name="e">Indeholder information omkring det specifikke event.</param>
        private void CreateTaskButton_Click(object sender, RoutedEventArgs e)
        {
            if (ProjectComboBox.SelectedItem as ProjectData != null)
            {
                if ((ProjectComboBox.SelectedItem as ProjectData).AssignedAdmin.Equals(currUser.Username))
                    HideOrShowNotifCreateTask();
                else
                    MessageBox.Show("You have to be project admin to edit a project", "Create Task!", MessageBoxButton.OK, MessageBoxImage.Stop);
            }
            else
                MessageBox.Show("Please make sure to choose a project before trying to create a task!", "Create Task", MessageBoxButton.OK, MessageBoxImage.Stop);
        }
        /// <summary>
        /// Event der køres når der klikkes på <c>CreateUserButton</c>.
        /// </summary>
        /// <remarks>
        /// Viset vinduet til at oprette nye brugere.
        /// </remarks>
        /// <param name="sender">Indeholder information om hvor eventet kommer fra.</param>
        /// <param name="e">Indeholder information omkring det specifikke event.</param>
        private void CreateUserButton_Click(object sender, RoutedEventArgs e)
        {
            HideOrShowNotifCreateUser();
        }
        /// <summary>
        /// Event der køres når der klikkes på <c>CreateProject</c>.
        /// </summary>
        /// <remarks>
        /// Viset vinduet til at oprette nye projekter.
        /// </remarks>
        /// <param name="sender">Indeholder information om hvor eventet kommer fra.</param>
        /// <param name="e">Indeholder information omkring det specifikke event.</param>
        private void CreateProjectButton_Click(object sender, RoutedEventArgs e)
        {
            HideOrShowNotifCreateProject();
        }
        /// <summary>
        /// Event der køres når der klikkes på <c>CreateGanttButton</c>.
        /// </summary>
        /// <remarks>
        /// Viset vinduet med Gantt chart i, hvis der er valgt et projekt.
        /// </remarks>
        /// <param name="sender">Indeholder information om hvor eventet kommer fra.</param>
        /// <param name="e">Indeholder information omkring det specifikke event.</param>
        private void CreateGanttButton_Click(object sender, RoutedEventArgs e)
        {
            if (ProjectComboBox.SelectedItem != null)
            {
                ProjectData pd = ProjectComboBox.SelectedItem as ProjectData;
                GanttChart.TotalTasks = 0;
                foreach (Task t in pd.TaskList)
                    GanttChart.TotalTasks++;
                HideOrShowGantt();
            }
            else
                MessageBox.Show("Please select a project in the drop menu before trying to generate a Gantt chart!", "Create Gantt chart", MessageBoxButton.OK, MessageBoxImage.Stop);
        }
        /// <summary>
        /// Event der køres når der klikkes på <c>ChangeAdminButton</c>.
        /// </summary>
        /// <remarks>
        /// Viset vinduet med mulighed for at skifte "ejer" af projektet.
        /// </remarks>
        /// <param name="sender">Indeholder information om hvor eventet kommer fra.</param>
        /// <param name="e">Indeholder information omkring det specifikke event.</param>
        private void ChangeAdminButton_Click(object sender, RoutedEventArgs e)
        {
            HideOrShowNotifChangeAdmin();
        }
        /// <summary>
        /// Event der køres når der åbnes for <c>ComboBox</c> med projekter.
        /// </summary>
        /// <remarks>
        /// Viser de forskellige projekter i databasen.
        /// </remarks>
        /// <param name="sender">Indeholder information om hvor eventet kommer fra.</param>
        /// <param name="e">Indeholder information omkring det specifikke event.</param>
        private void ProjectComboBox_DropDownOpened(object sender, EventArgs e)
        {
            RefreshProjectComboBox();
        }
        /// <summary>
        /// Event der køres når der vælges et nyt element i Projekt-<c>ComboBox</c>
        /// </summary>
        /// <remarks>
        /// Opdaterer listen med opgaver og informationen om projekter.
        /// </remarks>
        /// <param name="sender">Indeholder information om hvor eventet kommer fra.</param>
        /// <param name="e">Indeholder information omkring det specifikke event.</param>
        private void ProjectComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            RefreshTaskList();
            RefreshProjectLabelInfo();
        }
        /// <summary>
        /// Event der køres når <c>ServerIPTextBox</c> får fokus fra brugeren.
        /// </summary>
        /// <param name="sender">Indeholder information om hvor eventet kommer fra.</param>
        /// <param name="e">Indeholder information omkring det specifikke event.</param>
        private void ServerIPTextBox_GotFocus(object sender, RoutedEventArgs e)
        {
            InitializeTextBoxOnGotFocus(ServerIPTextBox, "127.0.0.1", ConnectButton);
        }
        /// <summary>
        /// Event der køres når <c>ServerIPTextBox</c> mister fokus fra brugeren.
        /// </summary>
        /// <param name="sender">Indeholder information om hvor eventet kommer fra.</param>
        /// <param name="e">Indeholder information omkring det specifikke event.</param>
        private void ServerIPTextBox_LostFocus(object sender, RoutedEventArgs e)
        {
            InitializeTextBoxOnLostFocus(ServerIPTextBox, "127.0.0.1");
        }
        /// <summary>
        /// Event der køres når <c>ServerPortTextBox</c> får fokus fra brugeren.
        /// </summary>
        /// <param name="sender">Indeholder information om hvor eventet kommer fra.</param>
        /// <param name="e">Indeholder information omkring det specifikke event.</param>
        private void ServerPortTextBox_GotFocus(object sender, RoutedEventArgs e)
        {
            InitializeTextBoxOnGotFocus(ServerPortTextBox, "8100", ConnectButton);
        }
        /// <summary>
        /// Event der køres når <c>ServerPortTextBox</c> mister fokus fra brugeren.
        /// </summary>
        /// <param name="sender">Indeholder information om hvor eventet kommer fra.</param>
        /// <param name="e">Indeholder information omkring det specifikke event.</param>
        private void ServerPortTextBox_LostFocus(object sender, RoutedEventArgs e)
        {
            InitializeTextBoxOnLostFocus(ServerPortTextBox, "8100");
        }
        /// <summary>
        /// Event der køres når <c>UsernameTextBox</c> får fokus fra brugeren.
        /// </summary>
        /// <param name="sender">Indeholder information om hvor eventet kommer fra.</param>
        /// <param name="e">Indeholder information omkring det specifikke event.</param>
        private void UsernameTextBox_GotFocus(object sender, RoutedEventArgs e)
        {
            InitializeTextBoxOnGotFocus(UsernameTextBox, "Username", ConnectButton);
        }
        /// <summary>
        /// Event der køres når <c>UsernameTextBox</c> mister fokus fra brugeren.
        /// </summary>
        /// <param name="sender">Indeholder information om hvor eventet kommer fra.</param>
        /// <param name="e">Indeholder information omkring det specifikke event.</param>
        private void UsernameTextBox_LostFocus(object sender, RoutedEventArgs e)
        {
            InitializeTextBoxOnLostFocus(UsernameTextBox, "Username");
        }
        /// <summary>
        /// Event der køres når <c>PasswordPasswordBox</c> får fokus fra brugeren.
        /// </summary>
        /// <param name="sender">Indeholder information om hvor eventet kommer fra.</param>
        /// <param name="e">Indeholder information omkring det specifikke event.</param>
        private void PasswordPasswordBox_GotFocus(object sender, RoutedEventArgs e)
        {
            if (PasswordPasswordBox.Password.Equals("Password") || string.IsNullOrWhiteSpace(PasswordPasswordBox.Password))
                PasswordPasswordBox.Clear();
            ConnectButton.IsDefault = true;
        }
        /// <summary>
        /// Event der køres når <c>PasswordPasswordBox</c> mister fokus fra brugeren.
        /// </summary>
        /// <param name="sender">Indeholder information om hvor eventet kommer fra.</param>
        /// <param name="e">Indeholder information omkring det specifikke event.</param>
        private void PasswordPasswordBox_LostFocus(object sender, RoutedEventArgs e)
        {
            if (string.IsNullOrWhiteSpace(PasswordPasswordBox.Password))
                PasswordPasswordBox.Password = "Password";
        }
        /// <summary>
        /// Event der køres når der klikkes på <c>ConnectButton</c>.
        /// </summary>
        /// <remarks>
        /// Sørger for at kalde <c>ConnectToServer</c> med inputs fra brugeren.
        /// </remarks>
        /// <param name="sender">Indeholder information om hvor eventet kommer fra.</param>
        /// <param name="e">Indeholder information omkring det specifikke event.</param>
        private void ConnectButton_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                ConnectToServer(ServerIPTextBox.Text, ServerPortTextBox.Text, UsernameTextBox.Text, PasswordPasswordBox.Password);
            }
            catch (ArgumentNullException)
            {
                MessageBox.Show("Failed to connect to server, make sure the information is correct!", "Connect to server", MessageBoxButton.OK, MessageBoxImage.Error);
            }
            catch (ArgumentOutOfRangeException)
            {
                MessageBox.Show("Server IP & Port must be a valid value!", "Connect to server", MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }
        /// <summary>
        /// Event der køres når der klikkes på <c>ConnectButton</c>.
        /// </summary>
        /// <remarks>
        /// Sørger for at kalde <c>DisconnectFromServer</c>.
        /// </remarks>
        /// <param name="sender">Indeholder information om hvor eventet kommer fra.</param>
        /// <param name="e">Indeholder information omkring det specifikke event.</param>
        private void DisconnectButton_Click(object sender, RoutedEventArgs e)
        {
            DisconnectFromServer();
        }
        #endregion

        #region Notif-menuer
        #region Create Project
        /// <summary>
        /// Nulstiller "tilføj projekt"-vinduet til oprindelig status
        /// </summary>
        private void NotifCreateProjectReset()
        {
            NotifCreateProjectProjectNameTextBox.Text = "Enter project name";
            NotifCreateProjectStartDT.SelectedDate = DateTime.Now;
            NotifCreateProjectEndDT.SelectedDate = DateTime.Now;
        }
        /// <summary>
        /// Event der køres når man vælger en starttid for en opgave
        /// </summary>
        /// <remarks>
        /// Sørger for at man ikke kan vælge et sluttidspunkt der er før starttidspunktet.
        /// </remarks>
        /// <param name="sender">Indeholder information om hvor eventet kommer fra.</param>
        /// <param name="e">Indeholder information omkring det specifikke event.</param>
        private void NotifCreateProjectStartDT_SelectedDateChanged(object sender, SelectionChangedEventArgs e)
        {
            NotifCreateProjectEndDT.DisplayDateStart = NotifCreateProjectStartDT.SelectedDate;
            NotifCreateProjectEndDT.DisplayDateEnd = DateTime.MaxValue;
            NotifCreateProjectEndDT.SelectedDate = NotifCreateProjectStartDT.SelectedDate;
        }
        /// <summary>
        /// Event der køres når <c>NotifCreateProjectProjectNameTextBox</c> får fokus fra brugeren.
        /// </summary>
        /// <param name="sender">Indeholder information om hvor eventet kommer fra.</param>
        /// <param name="e">Indeholder information omkring det specifikke event.</param>
        private void NotifCreateProjectProjectNameTextBox_GotFocus(object sender, RoutedEventArgs e)
        {
            InitializeTextBoxOnGotFocus(NotifCreateProjectProjectNameTextBox, "Enter project name", NotifCreateProjectAddButton);
        }
        /// <summary>
        /// Event der køres når <c>NotifCreateProjectProjectNameTextBox</c> mister fokus fra brugeren.
        /// </summary>
        /// <param name="sender">Indeholder information om hvor eventet kommer fra.</param>
        /// <param name="e">Indeholder information omkring det specifikke event.</param>
        private void NotifCreateProjectProjectNameTextBox_LostFocus(object sender, RoutedEventArgs e)
        {
            InitializeTextBoxOnLostFocus(NotifCreateProjectProjectNameTextBox, "Enter project name");
        }
        /// <summary>
        /// Event der køres når der klikkes på <c>NotifCreateProjectAddButton</c>.
        /// </summary>
        /// <remarks>
        /// Tilføjer projektet hvis det ikke indeholder en tom streng eller standard-teksten.
        /// </remarks>
        /// <param name="sender">Indeholder information om hvor eventet kommer fra.</param>
        /// <param name="e">Indeholder information omkring det specifikke event.</param>
        private void NotifCreateProjectAddButton_Click(object sender, RoutedEventArgs e)
        {
            if (!String.IsNullOrWhiteSpace(NotifCreateProjectProjectNameTextBox.Text) &&
                (!String.Equals("Enter project name", NotifCreateProjectProjectNameTextBox.Text)))
            {
                CreateProject(NotifCreateProjectProjectNameTextBox.Text,
                    NotifCreateProjectStartDT.SelectedDate.Value,
                    NotifCreateProjectEndDT.SelectedDate.Value);

                HideOrShowNotifCreateProject();
            }
        }
        /// <summary>
        /// Event der køres når der klikkes på <c>NotifCreateProjectCancelButton</c>.
        /// </summary>
        /// <remarks>
        /// Lukker vindet til at oprette projekter
        /// </remarks>
        /// <param name="sender">Indeholder information om hvor eventet kommer fra.</param>
        /// <param name="e">Indeholder information omkring det specifikke event.</param>
        private void NotifCreateProjectCancelButton_Click(object sender, RoutedEventArgs e)
        {
            HideOrShowNotifCreateProject();
        }
        #endregion

        #region Create Task
        /// <summary>
        /// Nulstiller "tilføj opgave"-vinduet til oprindelig status
        /// </summary>
        private void NotifCreateTaskReset()
        {
            NotifCreateTaskTaskNameTextBox.Text = "Enter task name";
            NotifCreateTaskTaskDescriptionTextBox.Text = "Enter task description";

            NotifCreateTaskStartDT.DisplayDateStart = (ProjectComboBox.SelectedItem as ProjectData).ProjectStart;
            NotifCreateTaskStartDT.DisplayDateEnd = (ProjectComboBox.SelectedItem as ProjectData).ProjectEnd;
            NotifCreateTaskStartDT.SelectedDate = (ProjectComboBox.SelectedItem as ProjectData).ProjectStart;

            NotifCreateTaskEndDT.DisplayDateStart = NotifCreateTaskStartDT.SelectedDate;
            NotifCreateTaskEndDT.DisplayDateEnd = (ProjectComboBox.SelectedItem as ProjectData).ProjectEnd;
            NotifCreateTaskEndDT.SelectedDate = NotifCreateTaskStartDT.SelectedDate;
        }
        /// <summary>
        /// Event der køres når man vælger en starttid for en opgave
        /// </summary>
        /// <remarks>
        /// Sørger for at man ikke kan vælge et sluttidspunkt der er før starttidspunktet.
        /// </remarks>
        /// <param name="sender">Indeholder information om hvor eventet kommer fra.</param>
        /// <param name="e">Indeholder information omkring det specifikke event.</param>
        private void NotifCreateTaskStartDT_SelectedDateChanged(object sender, SelectionChangedEventArgs e)
        {
            NotifCreateTaskEndDT.DisplayDateStart = NotifCreateTaskStartDT.SelectedDate;
            NotifCreateTaskEndDT.DisplayDateEnd = (ProjectComboBox.SelectedItem as ProjectData).ProjectEnd;
            NotifCreateTaskEndDT.SelectedDate = NotifCreateTaskStartDT.SelectedDate;
        }
        /// <summary>
        /// Event der køres når <c>NotifCreateTaskTaskNameTextBox</c> får fokus fra brugeren.
        /// </summary>
        /// <param name="sender">Indeholder information om hvor eventet kommer fra.</param>
        /// <param name="e">Indeholder information omkring det specifikke event.</param>
        private void NotifCreateTaskTaskNameTextBox_GotFocus(object sender, RoutedEventArgs e)
        {
            InitializeTextBoxOnGotFocus(NotifCreateTaskTaskNameTextBox, "Enter task name", NotifCreateTaskAddButton);
        }
        /// <summary>
        /// Event der køres når <c>NotifCreateTaskTaskNameTextBox</c> mister fokus fra brugeren.
        /// </summary>
        /// <param name="sender">Indeholder information om hvor eventet kommer fra.</param>
        /// <param name="e">Indeholder information omkring det specifikke event.</param>
        private void NotifCreateTaskTaskNameTextBox_LostFocus(object sender, RoutedEventArgs e)
        {
            InitializeTextBoxOnLostFocus(NotifCreateTaskTaskNameTextBox, "Enter task name");
        }
        /// <summary>
        /// Event der køres når <c>NotifCreateTaskTaskDescriptionTextBox</c> får fokus fra brugeren.
        /// </summary>
        /// <param name="sender">Indeholder information om hvor eventet kommer fra.</param>
        /// <param name="e">Indeholder information omkring det specifikke event.</param>
        private void NotifCreateTaskTaskDescriptionTextBox_GotFocus(object sender, RoutedEventArgs e)
        {
            InitializeTextBoxOnGotFocus(NotifCreateTaskTaskDescriptionTextBox, "Enter task description", NotifCreateTaskAddButton);
        }
        /// <summary>
        /// Event der køres når <c>NotifCreateTaskTaskDescriptionTextBox</c> får fokus fra brugeren.
        /// </summary>
        /// <param name="sender">Indeholder information om hvor eventet kommer fra.</param>
        /// <param name="e">Indeholder information omkring det specifikke event.</param>
        private void NotifCreateTaskTaskDescriptionTextBox_LostFocus(object sender, RoutedEventArgs e)
        {
            InitializeTextBoxOnLostFocus(NotifCreateTaskTaskDescriptionTextBox, "Enter task description");
        }
        /// <summary>
        /// Event der køres når der klikkes på <c>NotifCreateTaskAddButton</c>.
        /// </summary>
        /// <remarks>
        /// Tilføjer opgaven vis det ikke indeholder en tom streng eller standard-teksten.
        /// </remarks>
        /// <param name="sender">Indeholder information om hvor eventet kommer fra.</param>
        /// <param name="e">Indeholder information omkring det specifikke event.</param>
        private void NotifCreateTaskAddButton_Click(object sender, RoutedEventArgs e)
        {
            CreateTask(ProjectComboBox.SelectedItem as ProjectData,
                NotifCreateTaskTaskNameTextBox.Text,
                NotifCreateTaskTaskDescriptionTextBox.Text,
                NotifCreateTaskStartDT.SelectedDate.Value,
                NotifCreateTaskEndDT.SelectedDate.Value);

            NotifCreateTaskReset();
            NotifCreateTaskTaskNameTextBox.Focus();
        }
        /// /// <summary>
        /// Event der køres når der klikkes på <c>NotifCreateTaskCancelButton</c>.
        /// </summary>
        /// <remarks>
        /// Lukker vindet til at oprette opgaver.
        /// </remarks>
        /// <param name="sender">Indeholder information om hvor eventet kommer fra.</param>
        /// <param name="e">Indeholder information omkring det specifikke event.</param>
        private void NotifCreateTaskCancelButton_Click(object sender, RoutedEventArgs e)
        {
            HideOrShowNotifCreateTask();
        }
        #endregion

        #region Create User
        /// <summary>
        /// Nulstiller "tilføj bruger"-vinduet til oprindelig status
        /// </summary>
        private void NotifCreateUserReset()
        {
            NotifCreateUserUsernameTextbox.Text = "Enter username";
            NotifCreateUserPasswordPasswordBox.Password = "Password";
        }
        /// <summary>
        /// Event der køres når <c>NotifCreateUserPasswordPasswordBo</c> mister fokus fra brugeren.
        /// </summary>
        /// <param name="sender">Indeholder information om hvor eventet kommer fra.</param>
        /// <param name="e">Indeholder information omkring det specifikke event.</param>
        private void NotifCreateUserPasswordPasswordBox_LostFocus(object sender, RoutedEventArgs e)
        {
            if (string.IsNullOrWhiteSpace(NotifCreateUserPasswordPasswordBox.Password))
                NotifCreateUserPasswordPasswordBox.Password = "Password";
        }
        /// <summary>
        /// Event der køres når <c>NotifCreateUserPasswordPasswordBo</c> får fokus fra brugeren.
        /// </summary>
        /// <param name="sender">Indeholder information om hvor eventet kommer fra.</param>
        /// <param name="e">Indeholder information omkring det specifikke event.</param>
        private void NotifCreateUserPasswordPasswordBox_GotFocus(object sender, RoutedEventArgs e)
        {
            if (NotifCreateUserPasswordPasswordBox.Password.Equals("Password") || string.IsNullOrWhiteSpace(NotifCreateUserPasswordPasswordBox.Password))
                NotifCreateUserPasswordPasswordBox.Clear();
            NotifCreateUserAddButton.IsDefault = true;
        }
        /// <summary>
        /// Event der køres når <c>NotifCreateUserUsernameTextbox</c> får fokus fra brugeren.
        /// </summary>
        /// <param name="sender">Indeholder information om hvor eventet kommer fra.</param>
        /// <param name="e">Indeholder information omkring det specifikke event.</param>
        private void NotifCreateUserUsernameTextbox_GotFocus(object sender, RoutedEventArgs e)
        {
            InitializeTextBoxOnGotFocus(NotifCreateUserUsernameTextbox, "Enter username", NotifCreateUserAddButton);
        }
        /// <summary>
        /// Event der køres når <c>NotifCreateUserUsernameTextbox</c> mister fokus fra brugeren.
        /// </summary>
        /// <param name="sender">Indeholder information om hvor eventet kommer fra.</param>
        /// <param name="e">Indeholder information omkring det specifikke event.</param>
        private void NotifCreateUserUsernameTextbox_LostFocus(object sender, RoutedEventArgs e)
        {
            InitializeTextBoxOnLostFocus(NotifCreateUserUsernameTextbox, "Enter username");
        }
        /// <summary>
        /// Event der køres når der klikkes på <c>NotifCreateUserAddButton</c>.
        /// </summary>
        /// <remarks>
        /// Tilføjer bruger hvis den ikke indeholder en tom streng eller standard-teksten.
        /// </remarks>
        /// <param name="sender">Indeholder information om hvor eventet kommer fra.</param>
        /// <param name="e">Indeholder information omkring det specifikke event.</param>
        private void NotifCreateUserAddButton_Click(object sender, RoutedEventArgs e)
        {
            CreateUser(NotifCreateUserUsernameTextbox.Text, NotifCreateUserPasswordPasswordBox.Password);
            HideOrShowNotifCreateUser();
        }
        /// /// <summary>
        /// Event der køres når der klikkes på <c>NotifCreateUserCancelButton</c>.
        /// </summary>
        /// <remarks>
        /// Lukker vindet til at oprette brugere.
        /// </remarks>
        /// <param name="sender">Indeholder information om hvor eventet kommer fra.</param>
        /// <param name="e">Indeholder information omkring det specifikke event.</param>
        private void NotifCreateUserCancelButton_Click(object sender, RoutedEventArgs e)
        {
            HideOrShowNotifCreateUser();
        }
        #endregion

        #region Change admin
        /// <summary>
        /// Event der køres når <c>NotifChangeAdminUsernameTextBox</c> får fokus fra brugeren.
        /// </summary>
        /// <param name="sender">Indeholder information om hvor eventet kommer fra.</param>
        /// <param name="e">Indeholder information omkring det specifikke event.</param>
        private void NotifChangeAdminUsernameTextBox_GotFocus(object sender, RoutedEventArgs e)
        {
            InitializeTextBoxOnGotFocus(NotifChangeAdminUsernameTextBox, "Admin name", NotifChangeAdminAdd);
        }
        /// <summary>
        /// Event der køres når <c>NotifChangeAdminUsernameTextBox</c> mister fokus fra brugeren.
        /// </summary>
        /// <param name="sender">Indeholder information om hvor eventet kommer fra.</param>
        /// <param name="e">Indeholder information omkring det specifikke event.</param>
        private void NotifChangeAdminUsernameTextBox_LostFocus(object sender, RoutedEventArgs e)
        {
            InitializeTextBoxOnLostFocus(NotifChangeAdminUsernameTextBox, "Admin name");
        }
        /// <summary>
        /// Event der køres når der klikkes på <c>NotifChangeAdminAdd</c>.
        /// </summary>
        /// <remarks>
        /// Ændrer admin hvis man er nuværende admin og der er valgt et projekt.
        /// </remarks>
        /// <param name="sender">Indeholder information om hvor eventet kommer fra.</param>
        /// <param name="e">Indeholder information omkring det specifikke event.</param>
        private void NotifChangeAdminAdd_Click(object sender, RoutedEventArgs e)
        {
            ProjectData pd = ProjectComboBox.SelectedItem as ProjectData;
            if (pd != null)
            {
                if (pd.AssignedAdmin.Equals(currUser.Username))
                {
                    try
                    {
                        pd.AssignedAdmin = NotifChangeAdminUsernameTextBox.Text;
                        ProjectDB.Add(pd);

                        EDS.Encapsulation = new EncapsulationClass(pd);
                    }
                    catch (ArgumentException)
                    {
                        MessageBox.Show("Invalid arguments!", "Change admin", MessageBoxButton.OK, MessageBoxImage.Stop);
                    }
                    finally
                    {
                        HideOrShowNotifChangeAdmin();
                    }
                }
                else
                    MessageBox.Show("Can't change admin on a project you aren't the current admin!", "Change admin", MessageBoxButton.OK, MessageBoxImage.Stop);
            }
            else
                MessageBox.Show("Please pick a project to change admin for!", "Change admin", MessageBoxButton.OK, MessageBoxImage.Stop);

            RefreshProjectComboBox();
            ProjectComboBox.SelectedIndex = ProjectDB.IndexOf(pd);
        }
        /// /// <summary>
        /// Event der køres når der klikkes på <c>NotifChangeAdminCancel</c>.
        /// </summary>
        /// <remarks>
        /// Lukker vindet til at skifte admin.
        /// </remarks>
        /// <param name="sender">Indeholder information om hvor eventet kommer fra.</param>
        /// <param name="e">Indeholder information omkring det specifikke event.</param>
        private void NotifChangeAdminCancel_Click(object sender, RoutedEventArgs e)
        {
            HideOrShowNotifChangeAdmin();
        }
        #endregion
        #endregion

        #region Gantt
        /// <summary>
        /// Sætter størrelsen på det <c>Canvas</c> som Ganttcharten genereres i.
        /// </summary>
        /// <remarks>
        /// Heri sættes størrelsen på de variabler som betemmer størrelsen af Ganttchartens elementer og ud fra det sættes højden og bredden på det <c>Canvas</c> hvori Ganttcharten genereres.
        /// </remarks>
        /// <param name="pd">Projektet som den genererer Ganttcharten på baggrund af.</param>
        private void SetTaskCanvasSize(ProjectData pd)
        {
            double tempWidth = 0;
            double tempHeight = 0;

            if (pd != null)
            {
                GanttChart.SetOneDayPxSize(Gantt.ActualWidth, DaysBetweenTaskAndTask(pd.ProjectStart, pd.ProjectEnd));

                tempWidth = (
                            (DaysBetweenTaskAndTask(pd.ProjectStart, pd.ProjectEnd) * GanttChart.OneDayInPxWidth) +
                            (DaysBetweenTaskAndTask(pd.ProjectStart, pd.ProjectEnd) * GanttChart.ElementHorizontalPadding)
                            );

                double canvasHeight = ((GanttChart.TotalTasks * GanttChart.OneElementInPxHeight) + (GanttChart.TotalTasks * GanttChart.ElementVerticalPadding)); ;
                if (canvasHeight < GanttScrollviewer.ActualHeight)
                    tempHeight = GanttScrollviewer.ActualHeight;
                else
                    tempHeight = canvasHeight;
            }

            TaskCanvas.Width = tempWidth;
            TaskCanvas.Height = tempHeight;
        }
        /// <summary>
        /// Event der køres når størrelsen på <c>Canvas</c> hvor Ganttcharten er i ændres.
        /// </summary>
        /// <param name="sender">Indeholder information om hvor eventet kommer fra.</param>
        /// <param name="e">Indeholder information omkring det specifikke event.</param>
        private void Gantt_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            if (TaskCanvas.ActualWidth < Gantt.ActualWidth / 2 || TaskCanvas.ActualHeight < Gantt.ActualHeight / 2)
                RefreshGantt();
        }
        /// <summary>
        /// Metode der sørger for at "tegne" to bjælker i toppen af Ganttcharten med hhv. måneder og dato
        /// </summary>
        /// <param name="startDate">Starttidspunktet for Ganttcharten</param>
        /// <param name="endDate">Sluttidspunktet for Ganttcharten</param>
        private void DrawDateLine(DateTime startDate, DateTime endDate)
        {
            DateTime tempDiff = startDate;
            string labelText;
            int monthDrawed = 0;
            double xCoord = 0;
            double yCoord = 0;
            while (tempDiff <= endDate)
            {
                if (tempDiff.Month != monthDrawed)
                {
                    labelText = tempDiff.ToString("MMMM");
                    double daysInCurrentMonth = DateTime.DaysInMonth(tempDiff.Year, tempDiff.Month) - (tempDiff.Day - 1);
                    double monthInPx = (daysInCurrentMonth * GanttChart.OneDayInPxWidth) + ((daysInCurrentMonth - 1) * GanttChart.ElementVerticalPadding);
                    xCoord = GanttChart.GetElementXCoordinate(startDate, tempDiff) + GanttChart.ElementVerticalPadding;
                    yCoord = 0;
                    DrawLabel(xCoord, yCoord, monthInPx, labelText);
                    monthDrawed = tempDiff.Month;
                }

                labelText = tempDiff.Day.ToString();
                xCoord = GanttChart.GetElementXCoordinate(startDate, tempDiff) + GanttChart.ElementVerticalPadding;
                yCoord = GanttChart.OneElementInPxHeight + GanttChart.ElementHorizontalPadding;
                DrawLabel(xCoord, yCoord, GanttChart.OneDayInPxWidth, labelText);

                tempDiff = tempDiff.AddDays(1);
            }
        }
        /// <summary>
        /// Metode til at tegne opgaver ind i Ganttcharten
        /// </summary>
        /// <remarks>
        /// Kører igennem alle opgaver for at sætte x- og y-koordinaterne for alle opgaver og derefter lave en label på baggrund af den vha. <c>DrawLabelFromTask</c>-metoden.
        /// </remarks>
        /// <param name="pd">Projektet som opgaverne baseres på.</param>
        private void DrawGanttTaskBody(ProjectData pd)
        {
            double xCord = 0;
            double yCord;
            double taskLength;

            if (pd != null)
                foreach (Task t in pd.TaskList)
                {
                    yCord = ((pd.TaskList.IndexOf(t) + 2) * GanttChart.OneElementInPxHeight) + (GanttChart.ElementVerticalPadding * (pd.TaskList.IndexOf(t) + 2));
                    xCord = DaysBetweenProjectAndTask(pd.ProjectStart, t.TaskStart) * GanttChart.OneDayInPxWidth + (DaysBetweenProjectAndTask(pd.ProjectStart, t.TaskStart) * GanttChart.ElementHorizontalPadding);
                    taskLength = DaysBetweenTaskAndTask(t.TaskStart, t.TaskEnd) * GanttChart.OneDayInPxWidth + (DaysBetweenTaskAndTask(t.TaskStart, t.TaskEnd) * GanttChart.ElementHorizontalPadding);

                    DrawLabel(xCord, yCord, taskLength, t.TaskName);
                }
        }
        /// <summary>
        /// Genererer en label ud fra en række af informationer og placerer det i det <c>Canvas</c> hvor Ganttcharten genereres
        /// </summary>
        /// <param name="xCoordinate">X-koordinatet hvor labelen skal placeres</param>
        /// <param name="yCoordinate">Y-koordinatet hvor labelen skal placeres</param>
        /// <param name="taskLength">Længden af labelen</param>
        /// <param name="taskName">Den tekst som står på label'en</param>
        private void DrawLabel(double xCoordinate, double yCoordinate, double taskLength, string taskName)
        {
            Label lbl = GanttChart.CreateLabel(GanttChart.GanttFillColor, taskLength, GanttChart.OneElementInPxHeight, taskName);
            TaskCanvas.Children.Add(lbl);
            Canvas.SetTop(lbl, yCoordinate);
            Canvas.SetLeft(lbl, xCoordinate);
        }
        /// /// <summary>
        /// Lukker vindet med Ganttcharten
        /// </summary>
        /// <param name="sender">Indeholder information om hvor eventet kommer fra.</param>
        /// <param name="e">Indeholder information omkring det specifikke event.</param>
        private void GanttCloseButton_Click(object sender, RoutedEventArgs e)
        {
            HideOrShowGantt();
        }
        #endregion

        #region Initialization & GUI Refresh
        /// <summary>
        /// Metode der køres når der skal oprettes forbindelse til en server.
        /// </summary>
        private void Init()
        {
            DelegateChatMessage = new HandleChatMessage(AppendChatMessageToTextbox);
            DelegateProjectData = new HandleProjectData(AddProjectDataToList);
            DelegateConnectStatus = new ConnectStatus(ConnectedToServer);

            EventDrivenShare PushToNetwork = new EventDrivenShare(); //initializes events til at dele data med Netværks klassen
            EventDrivenShare PushToGUI = new EventDrivenShare(); //initializes events til at dele data med GUI klassen

            //initializere variabler krævet for at gøre netværket - her under tråden
            StreamHandler = new Network(PushToGUI, this);

            /* Initializere den grafiske bruger-grænseflade - 
             * og klassen der, når et event er raised af PushToGUI, skal kalde BeginInvoke
             * (BeginInvoke sætter kaldet i kø, så en operation ikke bliver interupttet uforventet) på GUI-tråden 
            */
            GuiInputHandler GuiEventListener = new GuiInputHandler(this);

            //Tilføjer event-listeners
            PushToNetwork.DataToSendChange += StreamHandler.clientSend;
            PushToGUI.ChatMessageChange += GuiEventListener.PushChatMessage;
            PushToGUI.ProjectChange += GuiEventListener.PushProjectData;
            EDS = PushToNetwork;
        }
        /// <summary>
        /// Gør GUI'en klar til at logge ind.
        /// </summary>
        /// <remarks>
        /// Sørger for at aktivere knapper og sætter indholdet af opgavelisten til at være en DataBinding til det valgte projekts opgaveliste.
        /// </remarks>
        private void PrepareUIForLogin()
        {
            EnableButtonsOnLogin();
            ConnectMenuLoggedIn();
            if (ProjectComboBox.SelectedIndex >= 0)
            {
                TaskList.DataContext = ProjectDB.GetObservableTaskList(ProjectComboBox.SelectedItem as ProjectData);
            }
        }
        /// <summary>
        /// Gør GUI'en klar til at logge ud.
        /// </summary>
        /// <remarks>
        /// Sørger for at deaktivere knapper, og kører <c>ClearUI</c> så GUI'en nulstilles.
        /// </remarks>
        private void PrepareUIForLogout()
        {
            DisableButtonsOnLogout();
            ConnectMenuLoggedOut();
            ClearUI();
        }
        /// <summary>
        /// Metode til at aktivere knapperne der kan bruges i GUI'en
        /// </summary>
        private void EnableButtonsOnLogin()
        {
            MainMenuStackPanel.IsEnabled = true;
            RightGridInMotherGrid.IsEnabled = true;
            MiddleGridInMotherGrid.IsEnabled = true;
        }
        /// <summary>
        /// Metode til at deaktivere knapperne der kan bruges i GUI'en
        /// </summary>
        private void DisableButtonsOnLogout()
        {
            MainMenuStackPanel.IsEnabled = false;
            RightGridInMotherGrid.IsEnabled = false;
            MiddleGridInMotherGrid.IsEnabled = false;
        }
        /// <summary>
        /// Metode til at nulstille hele GUI'en
        /// </summary>
        private void ClearUI()
        {
            ChatTextBox.Clear();
            TaskList.DataContext = null;
            ProjectComboBox.SelectedIndex = 0;
            ProjectInfoLabel.Content = "";
        }
        /// <summary>
        /// Metode der sætter "ConnectMenu"'en til "logged in" tilstand.
        /// </summary>
        private void ConnectMenuLoggedIn()
        {
            DisconnectButton.IsEnabled = true;
            ConnectButton.IsEnabled = false;
            ServerIPTextBox.IsEnabled = false;
            ServerPortTextBox.IsEnabled = false;
            UsernameTextBox.IsEnabled = false;
            PasswordPasswordBox.IsEnabled = false;
        }
        /// <summary>
        /// Metode der sætter "ConnectMenu"'en til en "logged out" tilstand.
        /// </summary>
        private void ConnectMenuLoggedOut()
        {
            DisconnectButton.IsEnabled = false;
            ConnectButton.IsEnabled = true;
            ServerIPTextBox.IsEnabled = true;
            ServerPortTextBox.IsEnabled = true;
            UsernameTextBox.IsEnabled = true;
            PasswordPasswordBox.IsEnabled = true;
        }
        /// <summary>
        /// En metode der kan anvendes til at instatiere en tekstboks når den  mister fokus.
        /// </summary>
        /// <remarks>
        /// Sørger for at nulstille en tekstboks når den ikke er fokuseret mere. Nulstiller til "standard"-teksten
        /// Nulstiller kun hvis teksten deri kun er whitespace
        /// </remarks>
        /// <param name="textBox">Tekstboksen som skal instantieres</param>
        /// <param name="defaultText">"Standard"-teksten</param>
        private void InitializeTextBoxOnLostFocus(TextBox textBox, string defaultText)
        {
            if (string.IsNullOrWhiteSpace(textBox.Text))
                textBox.Text = defaultText;
        }
        /// <summary>
        /// En metode der kan anvendes til at instantiere en tekstboks når den får fokus.
        /// </summary>
        /// <remarks>
        /// Sørger for at nulstille en tekstboks når den bliver fokuseret. Nulstiller til en tom tekst.
        /// Nulstiller kun hvis teksten i forvejen er "standard"-teksten eller whitespace.
        /// </remarks>
        /// <param name="textBox">Tekstenboksen som skal instantieres.</param>
        /// <param name="defaultText">"Standard"-teksten.</param>
        /// <param name="defaultButton">Knappen som sættes til at være default-knappen.</param>
        private void InitializeTextBoxOnGotFocus(TextBox textBox, string defaultText, Button defaultButton)
        {
            if (textBox.Text == defaultText || string.IsNullOrWhiteSpace(textBox.Text))
                textBox.Clear();
            defaultButton.IsDefault = true;
        }
        /// <summary>
        /// Metode der Opdaterer den <c>ComboBox</c> hvor projekterne er listet.
        /// </summary>
        private void RefreshProjectComboBox()
        {
            ProjectComboBox.ItemsSource = ProjectDB.GetObservableProjects();
            RefreshProjectLabelInfo();
        }
        /// <summary>
        /// Metode der Opdaterer tasklisten for det valgte projekt.
        /// </summary>
        private void RefreshTaskList()
        {
            if ((ProjectComboBox.SelectedItem as ProjectData) != null)
                TaskList.DataContext = ProjectDB.GetObservableTaskList(ProjectComboBox.SelectedItem as ProjectData);
        }
        /// <summary>
        /// Metode der Opdaterer projekt-info'en for det valgte projekt.
        /// </summary>
        private void RefreshProjectLabelInfo()
        {
            ProjectData pd = ProjectComboBox.SelectedItem as ProjectData;
            if (pd != null)
            {
                string projectStartDate = "Project start date:\n" + pd.ProjectStart.Month + "/" + pd.ProjectStart.Day + "/" + pd.ProjectStart.Year;
                string projectEndDate = "Project end date:\n" + pd.ProjectEnd.Month + "/" + pd.ProjectEnd.Day + "/" + pd.ProjectEnd.Year;
                string projectAdmin = "Admin for this project is:\n" + "\"" + pd.AssignedAdmin + "\"";
                string newLine = "\n";
                ProjectInfoLabel.Content = projectStartDate + newLine + projectEndDate + newLine + projectAdmin;
            }
            else
                ProjectInfoLabel.Content = "";
        }
        /// <summary>
        /// Metode der Opdaterer Ganttcharten.
        /// </summary>
        /// <remarks>
        /// Sørger for at nulstille det <c>Canvas</c> hvori Ganttcharten er, og renderer derefter Ganttcharten forfra.
        /// </remarks>
        private void RefreshGantt()
        {
            TaskCanvas.Children.Clear();
            GanttChart.OneElementInPxHeight = 30;

            if ((ProjectComboBox.SelectedItem as ProjectData) != null)
            {
                SetTaskCanvasSize((ProjectComboBox.SelectedItem as ProjectData));
                DrawDateLine((ProjectComboBox.SelectedItem as ProjectData).ProjectStart, ((ProjectComboBox.SelectedItem as ProjectData).ProjectEnd));
                DrawGanttTaskBody((ProjectComboBox.SelectedItem as ProjectData));
            }
        }
        /// <summary>
        /// Metode der gennemtvinger en opdatering af hele GUI'en.
        /// </summary>
        /// <remarks>
        /// Kalder alle "opdaterings"-funktioner.
        /// </remarks>
        private void ForceGUIRefresh()
        {
            RefreshProjectComboBox();
            RefreshProjectLabelInfo();
            RefreshTaskList();
            RefreshGantt();
        }
        /// <summary>
        /// Viser/Skjuler vindet til at oprette opgaver.
        /// </summary>
        /// <remarks>
        /// Sørger for at aktivere/deaktivere knapperne og ændre visibility alt efter tilstand.
        /// Flytter fokus til den første tekstboks og sætter <c>IsCancel</c> til den rigtige knap.
        /// </remarks>
        private void HideOrShowNotifCreateTask()
        {
            if (!NotifCreateTask.IsEnabled)
            {
                NotifCreateTask.IsEnabled = true;
                NotifCreateTaskReset();
                NotifCreateTask.Visibility = System.Windows.Visibility.Visible;
                NotifCreateTaskCancelButton.IsCancel = true;
                NotifCreateTaskTaskNameTextBox.Focus();
            }
            else
            {
                NotifCreateTask.Visibility = System.Windows.Visibility.Collapsed;
                NotifCreateTask.IsEnabled = false;
            }
        }
        /// <summary>
        /// Viser/Skjuler vindet til at oprette projekter.
        /// </summary>
        /// <remarks>
        /// Sørger for at aktivere/deaktivere knapperne og ændre visibility alt efter tilstand.
        /// Flytter fokus til den første tekstboks og sætter <c>IsCancel</c> til den rigtige knap.
        /// </remarks>
        private void HideOrShowNotifCreateProject()
        {
            if (NotifCreateProject.IsEnabled)
            {
                NotifCreateProject.Visibility = System.Windows.Visibility.Collapsed;
                NotifCreateProject.IsEnabled = false;
            }
            else
            {
                NotifCreateProject.IsEnabled = true;
                NotifCreateProjectReset();
                NotifCreateProject.Visibility = System.Windows.Visibility.Visible;
                NotifCreateProjectCancelButton.IsCancel = true;
            }

        }
        /// <summary>
        /// Viser/Skjuler vindet til at oprette brugere.
        /// </summary>
        /// <remarks>
        /// Sørger for at aktivere/deaktivere knapperne og ændre visibility alt efter tilstand.
        /// Flytter fokus til den første tekstboks og sætter <c>IsCancel</c> til den rigtige knap.
        /// </remarks>
        private void HideOrShowNotifCreateUser()
        {
            if (NotifCreateUser.IsEnabled)
            {
                NotifCreateUser.Visibility = System.Windows.Visibility.Collapsed;
                NotifCreateUser.IsEnabled = false;
            }
            else
            {
                NotifCreateUser.IsEnabled = true;
                NotifCreateUserReset();
                NotifCreateUser.Visibility = System.Windows.Visibility.Visible;
                NotifCreateUserCancelButton.IsCancel = true;
            }
        }
        /// <summary>
        /// Viser/Skjuler vindet med Ganttcharten.
        /// </summary>
        /// <remarks>
        /// Sørger for at aktivere/deaktivere knapperne og ændre visibility alt efter tilstand.
        /// Flytter fokus til den første tekstboks og sætter <c>IsCancel</c> til den rigtige knap.
        /// Opdaterer derudover Ganttcharten
        /// </remarks>
        private void HideOrShowGantt()
        {
            if (Gantt.IsEnabled)
            {
                Gantt.Visibility = System.Windows.Visibility.Collapsed;
                GanttCloseButton.IsEnabled = false;
                Gantt.IsEnabled = false;
            }
            else
            {
                Gantt.IsEnabled = true;
                GanttCloseButton.IsEnabled = true;
                GanttCloseButton.IsCancel = true;
                Gantt.Visibility = System.Windows.Visibility.Visible;
                RefreshGantt();
            }

        }
        /// <summary>
        /// Viser/Skjuler vindet til at skifte admin for et projekt
        /// </summary>
        /// <remarks>
        /// Sørger for at aktivere/deaktivere knapperne og ændre visibility alt efter tilstand.
        /// Flytter fokus til den første tekstboks og sætter <c>IsCancel</c> til den rigtige knap.
        /// </remarks>
        private void HideOrShowNotifChangeAdmin()
        {
            if (NotifChangeAdmin.IsEnabled)
            {
                NotifChangeAdmin.IsEnabled = false;
                NotifChangeAdmin.Visibility = System.Windows.Visibility.Collapsed;
            }
            else
            {
                NotifChangeAdmin.IsEnabled = true;
                NotifChangeAdmin.Visibility = System.Windows.Visibility.Visible;
                NotifChangeAdminAdd.IsDefault = true;
                NotifChangeAdminCancel.IsCancel = true;
            }
        }
        /// <summary>
        /// Event der køres når <c>BackgroundWindow</c> (hovedvinduet) ændrer størrelse.
        /// </summary>
        /// <param name="sender">Indeholder information om hvor eventet kommer fra.</param>
        /// <param name="e">Indeholder information omkring det specifikke event.</param>
        private void BackgroundWindow_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            ForceGUIRefresh();
        }
        /// <summary>
        /// Event der køres når <c>BackgroundWindow</c> (hovedvinduet) lukkes.
        /// </summary>
        /// <remarks>
        /// Sørger for at lukke stream'en korrekt.
        /// </remarks>
        /// <param name="sender">Indeholder information om hvor eventet kommer fra.</param>
        /// <param name="e">Indeholder information omkring det specifikke event.</param>
        private void BackgroundWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            if (StreamHandler != null)
                StreamHandler.Disconnect();
        }
        /// <summary>
        /// Event der køres når der trykkes F1,F2, F3 eller F5 i programmet.
        /// </summary>
        /// <remarks>
        /// Viser hhv. hjælp, klient download, server download eller gennemtvinger opdatering af hele GUI'en
        /// </remarks>
        /// <param name="sender">Indeholder information om hvor eventet kommer fra.</param>
        /// <param name="e">Indeholder information omkring det specifikke event.</param>
        private void BackgroundWindow_KeyDown(object sender, KeyEventArgs e)
        {
            switch (e.Key)
            {
                case Key.F1:
                    if (HelpGrid.IsEnabled)
                    {
                        HelpGrid.Visibility = System.Windows.Visibility.Collapsed;
                        HelpGrid.IsEnabled = false;
                    }
                    else
                    {
                        HelpGrid.IsEnabled = true;
                        HelpGrid.Visibility = System.Windows.Visibility.Visible;
                        HelpBrowser.Navigate(new Uri("http://spriz.zapto.org/p2/html/"));
                    }
                    break;
                case Key.F2:
                    if (HelpGrid.IsEnabled)
                    {
                        HelpGrid.Visibility = System.Windows.Visibility.Collapsed;
                        HelpGrid.IsEnabled = false;
                    }
                    else
                    {
                        HelpGrid.IsEnabled = true;
                        HelpGrid.Visibility = System.Windows.Visibility.Visible;
                        HelpBrowser.Navigate(new Uri("http://spriz.zapto.org/p2/client/publish.htm"));
                    }
                    break;
                case Key.F3:
                    if (HelpGrid.IsEnabled)
                    {
                        HelpGrid.Visibility = System.Windows.Visibility.Collapsed;
                        HelpGrid.IsEnabled = false;
                    }
                    else
                    {
                        HelpGrid.IsEnabled = true;
                        HelpGrid.Visibility = System.Windows.Visibility.Visible;
                        HelpBrowser.Navigate(new Uri("http://spriz.zapto.org/p2/server/publish.htm"));
                    }
                    break;
                case Key.F5:
                    ForceGUIRefresh();
                    MessageBox.Show("Graphical user interface has been updated", "GanttMaker", MessageBoxButton.OK, MessageBoxImage.Information);
                    break;
            }
        }
        #endregion

        #region Network
        /// <summary>
        /// Metode til at oprette forbindelse til en server.
        /// </summary>
        /// <remarks>
        /// Instantierer netværkstråden og sætter den som en baggrundstråd således den lukkes når hoved-tråden lukkes.
        /// Instantierer ligeledes <c>EventDrivenShare</c> når forbindelsen er oprettet til serveren.
        /// Hvis der ikke kunne oprettes forbindelse, vises en passende <c>MessageBox</c>
        /// </remarks>
        /// <param name="ipIn">IP-Adressen der skal oprettes forbindelse til.</param>
        /// <param name="portIn">Port som der skal oprettes forbindelse via.</param>
        /// <param name="username"></param>
        /// <param name="password"></param>
        private void ConnectToServer(string ipIn, string portIn, string username, string password)
        {
            Init();

            User tempUser = new User(username, password);
            int port;
            IPAddress ipAdress;

            if (int.TryParse(portIn, out port) && IPAddress.TryParse(ipIn, out ipAdress))
            {
                if (StreamHandler.TryConnect(ipAdress, port, tempUser))
                {
                    NetThread = new Thread(StreamHandler.ClientRecv);
                    NetThread.IsBackground = true;
                    NetThread.Start();
                    EDS.Encapsulation = new EncapsulationClass(tempUser);
                }
                else
                    throw new ArgumentNullException("Failed to connect to server, make sure the information is correct!");
            }
            else
                throw new ArgumentOutOfRangeException("Server IP & Port must be a valid value!");
        }
        /// <summary>
        /// Metode til at afbryde forbindelsen fra serveren.
        /// </summary>
        /// <remarks>
        /// Sørger for at gøre GUI'en i "lougged out"-tilstand.
        /// Sørger for at lukke netværkstråden korrekt.
        /// </remarks>
        private void DisconnectFromServer()
        {
            PrepareUIForLogout();
            currUser = null;
            NetThread.Abort();
            StreamHandler.Disconnect();
            MessageBox.Show("Disconnected from server");
        }
        /// <summary>
        /// BAAAK?
        /// </summary>
        /// <param name="Message">BAAK?</param>
        public delegate void ConnectStatus(object Message); // Hva faen?

        private void ConnectedToServer(object userIn)
        {
            User tempUser = (User)userIn;
            if (tempUser.isValid)
            {
                currUser = tempUser;
                PrepareUIForLogin();
                MessageBox.Show("Connected!");
            }
            else
            {
                MessageBox.Show("Failed to verify user");
                NetThread.Abort();
                if (NetThread.ThreadState.Equals(ThreadState.AbortRequested))
                    StreamHandler.Disconnect();
            }
            Mouse.OverrideCursor = Cursors.Arrow;
        }
        #endregion

        #region Misc
        /// <summary>
        /// Sørger for at konvertere to DateTimes TimeSpan til et antal dage.
        /// </summary>
        /// <remarks>
        /// Anvendes til at sammenligne to tasks. Output bruges til visualisering af Gantt charten.
        /// </remarks>
        /// <param name="startTime">Starttidspunktet</param>
        /// <param name="endTime">Sluttidspunktet</param>
        /// <returns>
        /// Retunerer antallet af dage imellem de to datoer i en int32.
        /// hvis der er "0" dage (de starter og slutter samme dag) returneres 1.
        /// </returns>
        public static int DaysBetweenTaskAndTask(DateTime startTime, DateTime endTime)
        {
            int toReturn = Convert.ToInt32((endTime.Date - startTime.Date).TotalDays);
            if (toReturn > 0)
                return toReturn + 1;
            return 1;
        }
        /// <summary>
        /// Sørger for at konvertere to DateTimes TimeSpan til et antal dage.
        /// </summary>
        /// <remarks>
        /// Anvendes til at sammenligne en task og et project. Output bruges til visualisering af Gantt charten.
        /// </remarks>
        /// <param name="startTime">Starttidspunktet</param>
        /// <param name="endTime">Sluttidspunktet</param>
        /// <returns>
        /// Retunerer antallet af dage imellem de to datoer i en int32.
        /// </returns>
        public static int DaysBetweenProjectAndTask(DateTime startTime, DateTime endTime)
        {
            return Convert.ToInt32((endTime.Date - startTime.Date).TotalDays);
        }
        #endregion
    }
}